﻿using System;
using System.IO;
using Microsoft.Practices.RecipeFramework.VisualStudio.Templates;
using Microsoft.VisualStudio.TemplateWizard;
using System.Collections.Generic;
using EnvDTE;
using DDDProject.Guidance.Utils.ExtensionMethods;

namespace DDDProject.Guidance.Utils.CustomWizards
{
    public class SolutionWizard : UnfoldTemplate
    {
        public SolutionWizard()
        {
        }

        private DTE _dte;
        private DirectoryInfo _guidanceInstallDir;
        private string _solutionDir;
        private Dictionary<string, string> _replacementsDictionary;

        public override void RunStarted(
            object automationObject,
            Dictionary<string, string> replacementsDictionary,
            WizardRunKind runKind,
            object[] customParams)
        {
            _dte = (DTE)automationObject;
            _replacementsDictionary = replacementsDictionary;

            // Retrieve guidance installation folder
            _guidanceInstallDir = new FileInfo(customParams[0].ToString()) // Points to GuidanceInstallDir\Templates\Solution\Solution.vstemplate
                                                    .Directory // Points to GuidanceInstallDir\Templates\Solution\
                                                    .Parent // Points to GuidanceInstallDir\Templates\
                                                    .Parent; // Points to GuidanceInstallDir\

            // Retrieve Solution folder
            _solutionDir = replacementsDictionary["$destinationdirectory$"];

            // Copy external libs to solution folder
            CopyExternalLibsFiles();

            // Call base implementation
            base.RunStarted(automationObject, replacementsDictionary, runKind, customParams);
        }

        public override void RunFinished()
        {
            // Copy config files to solution folder
            CopyConfigFiles();

            // Call base implementation
            base.RunFinished();
        }

        private void CopyExternalLibsFiles()
        {
            // Retrieve ExternalLibs source folder
            DirectoryInfo externalLibsDir = new DirectoryInfo(_guidanceInstallDir.FullName + @"\ExternalLibs\");

            // Retrieve destination folder for ExternalLibs (ie. inside folder that will contain the newly created solution)
            DirectoryInfo destinationDir = new DirectoryInfo(_solutionDir + @"\ExternalLibs\");

            // Copy ExternalLibs to destination folder
            externalLibsDir.Copy(destinationDir);
        }

        private void CopyConfigFiles()
        {
            // Retrieve Config source folder
            DirectoryInfo configDir = new DirectoryInfo(_guidanceInstallDir.FullName + @"\Config\");

            // Retrieve destination folder for Config (ie. inside folder that contains the newly created solution)
            DirectoryInfo destinationDir = new DirectoryInfo(_solutionDir + @"\Config\");

            // Copy files to destination folder
            configDir.Copy(destinationDir);

            // Replace parameters in config files
            foreach (FileInfo file in destinationDir.GetFiles())
            {
                ReplaceParameters(file.FullName);
            }

            // Find Config solution folder
            Project configSolutionFolder = null;
            foreach (Project prj in _dte.Solution.Projects)
            {
                if (prj.Name == "Config")
                {
                    configSolutionFolder = prj;
                    break;
                }
            }

            // Add config files to Config solution folder
            foreach (FileInfo file in destinationDir.GetFiles())
            {
                AddItem(file.FullName, configSolutionFolder);
            }
        }

        private void ReplaceParameters(string filePath)
        {
            // Load file content
            string fileContent = String.Empty;
            using (StreamReader sr = new StreamReader(filePath))
            {
                fileContent = sr.ReadToEnd();
            }

            // Replace parameters
            foreach (string key in _replacementsDictionary.Keys)
            {
                fileContent = fileContent.Replace(key, _replacementsDictionary[key]);
            }

            // Write file
            using (StreamWriter sw = new StreamWriter(filePath, false))
            {
                sw.Write(fileContent);
            }
        }

        private void AddItem(string filePath, Project project)
        {
            // Add file to project
            project.ProjectItems.AddFromFile(filePath);

            // Close the file (a bug of VS displays the file in a new window...)
            _dte.ActiveWindow.Close(EnvDTE.vsSaveChanges.vsSaveChangesNo);
        }
    }
}
